package ah.szxy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 基于Sentinel的服务消费者启动类
 *
 * @author TimePause
 * @create 2020-09-13 21:05
 */
@SpringBootApplication
@RestController
@EnableDiscoveryClient
public class SentinelConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SentinelConsumerApplication.class);
    }

    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate() {//将远程调用对象注入到Spring容器
        return new RestTemplate();
    }

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 远程调用测试
     * @return
     */
    @SentinelResource(value = "rpc", fallback = "rpcFallBack", blockHandler = "rpcHandler")
    @GetMapping("/rpc")
    public ResponseEntity<String> rpc(String type) {
        System.out.println("调用远程服务 rpc");
        if(null != type && type.equals("java")) {
            throw new RuntimeException("不想成功 ...");
        }
        ResponseEntity<String> result = this.restTemplate.getForEntity(
                "http://sentinel-provider/test",
                String.class
        );
        if (result.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用 success");
        }
        throw new RuntimeException("远程调用失败 ...");
        // return ResponseEntity.badRequest().body("远程调用失败 ...");
    }

    /**
     * 服务降级
     * @param e
     * @return
     */
    public ResponseEntity rpcFallBack(String type, Throwable e) {
        return ResponseEntity.ok("异常类型为 "+type+",发生 java 异常, 异常信息为 ：" + e);
    }

    /**
     * block 方法回退
     * @param type
     * @param e
     * @return
     */
    public ResponseEntity rpcHandler(String type, BlockException e) {
        return ResponseEntity.ok("异常类型为" + type + ",sentinel 流控规则错误, 错误信息为：" + e);
    }
}
